/*
 * Copyright (C) 2010 TopCoder Inc., All Rights Reserved.
 */
package com.hercules.android.receiver.entities;

import java.lang.reflect.Field;

import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.hercules.android.receiver.Config;
import com.hercules.android.receiver.XREObjectFormatterException;

/**
 * <p>
 * The base class of all XRE resource.
 * </p>
 * 
 * @author TCSASSEMBER
 * @version 1.0
 */
public class XREObject {
    /**
     * Represents the resource id.
     */
    protected Integer id;

    /**
     * Represents the resource class.
     */
    protected String klass;

    /**
     * Default constructor. Set the default values.
     */
    public XREObject() {
        klass = "";
    }

    /**
     * Gets the resource id.
     * 
     * @return resource id
     */
    public Integer getId() {
        return id;
    }

    /**
     * Sets resource id.
     * 
     * @param id
     *            resource id
     */
    public void setId(Integer id) {
        this.id = id;
    }

    /**
     * Gets the resource class.
     * 
     * @return the resource class
     */
    public String getKlass() {
        return klass;
    }

    /**
     * Sets the resource class.
     * 
     * @param klass
     *            the resource class
     */
    public void setKlass(String klass) {
        this.klass = klass;
    }

    /**
     * Set properties from <code>JSONObject</code>.
     * 
     * @param json
     *            the <code>JSONObject</code> instance
     * @throws XREObjectFormatterException
     *             if any error occurs
     */
    public void setProperties(JSONObject json) throws XREObjectFormatterException {
        try {
            // set id to the base class XREObject
            if (json.has("id")) {
                id = json.getInt("id");
            }
            // set klass to the base class XREObject
            if (json.has("klass")) {
                klass = json.getString("klass");
            }
            // if the message contains params (NEW command) or props (SET command), then set these properties to object
            // using reflection
            if (json.has("params") || json.has("props")) {
                if (json.has("params")) {
                    json = json.getJSONObject("params");
                } else {
                    json = json.getJSONObject("props");
                }
                // Get the fields of this object
                Field[] fields = this.getClass().getDeclaredFields();
                for (Field field : fields) {
                    if (json.has(field.getName())) {
                        field.setAccessible(true);
                        Object value = json.get(field.getName());
                        // only set the properties if they are the some type
                        if (field.getType().isAssignableFrom(value.getClass())) {
                            Log.v(Config.APPLICATION_NAME, "set property: " + field.getName());
                            field.set(this, value);
                        }
                    }
                }
            }
        } catch (IllegalAccessException e) {
            throw new XREObjectFormatterException("Can't set properties.", e);
        } catch (JSONException e) {
            throw new XREObjectFormatterException("Error occurs when reading from JSON object.", e);
        }
    }
}
